package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.context.FlowElementProcessContext;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.CustomPropertiesProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.ExpressionUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.StringUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ConstanceVariable;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.ModelTaskCandidateSettings;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.model.FlowNodeCandidateControllerDomain;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowNodeCandidateControllerRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowTaskCandidateSettingsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Iterator;
import java.util.Objects;

/**
 * @Description 保存流程部署候选人信息进程
 * @author liujj
 * @date 2021-10-19
 * @version 1.0
 */
@Component
public class SaveDeployCandidateInfoProcessor implements CustomPropertiesProcessor {

    @Autowired
    private FlowTaskCandidateSettingsRepository flowTaskCandidateSettingsRepository;

    @Autowired
    private FlowNodeCandidateControllerRepository flowNodeCandidateControllerRepository;

    private void saveTaskDeployCandidateSettingsInfo(String deployId, JsonNode elementJson, JsonNode modelJson) {
        ObjectNode properties = (ObjectNode) elementJson.get("properties");
        JsonNode nodes = properties.get("candidateUsers");
        if (isInvalidConfig(nodes)) {
            return;
        }
        JsonNode nodeCode = properties.get("overrideid");
        if (StringUtils.isEmpty(nodeCode.textValue())) {
            return;
        }
        ObjectNode modelProperties = (ObjectNode) modelJson.get("properties");
        JsonNode modelVariables = modelProperties.get("modelVariables");
        if (Objects.isNull(modelVariables)) {
            return;
        }
        // 定义强制弹出选人变量
        String forcePick = null;
        JsonNode forcePickNode = properties.get("forcePick");
        if (forcePickNode == null) {
            forcePick = "0";
        } else {
            forcePick = forcePickNode.textValue();
        }
        // 指定下一节点处理人按钮权限
        JsonNode nodeAuth = properties.get("nodeAuth");
        if (Objects.isNull(nodeAuth)) {
            return;
        }
        JsonNode nextNodeHandlerNode = nodeAuth.get("nextNodeHandler");
        String nextNodeHandler = "0";
        if (!Objects.isNull(nextNodeHandlerNode) && nextNodeHandlerNode.asBoolean()) {
            nextNodeHandler = "1";
        }
        // 获取当前节点指定的可控制节点列表
        JsonNode controlNode = properties.get("controlNode");
        // 循环候选人用户组列表
        Iterator<JsonNode> itr = nodes.iterator();
        String controlNodeStr = Objects.isNull(controlNode) ? null : controlNode.toString();
        while (itr.hasNext()) {
            JsonNode temp = itr.next();
            if ("VAR".equalsIgnoreCase(temp.get("type").textValue())){
                String varType = temp.get("varType").textValue();
                String varCode = temp.get("code").textValue();
                String varName = temp.get("name").textValue();
                String code = "", name = "", type = "", codeVar = "", nameVar = "";
                ArrayNode arrayNode = (ArrayNode) modelVariables;
                if (arrayNode!=null && arrayNode.size()>0) {
                    for (JsonNode entry : arrayNode) {
                        type = entry.get("type").textValue();
                        codeVar = entry.get("code").textValue();
                        nameVar = entry.get("name").textValue();
                        if (type.equalsIgnoreCase(varType) && codeVar.equalsIgnoreCase(varCode) && nameVar.equalsIgnoreCase(varName)) {
                            code = codeVar;
                            name = nameVar;
                            if (!ExpressionUtils.isExpression(code)) {
                                code = "${".concat(code).concat("}");
                            }
                            ModelTaskCandidateSettings taskCandidateSettings = new ModelTaskCandidateSettings();
                            taskCandidateSettings.setDeployId(deployId);
                            taskCandidateSettings.setNodeCode(nodeCode.textValue());
                            taskCandidateSettings.setDataType(ConstanceVariable.VAR);
                            taskCandidateSettings.setCandidateType(varType);
                            taskCandidateSettings.setCandidateName(name);
                            taskCandidateSettings.setCandidateValue(code);
                            taskCandidateSettings.setForcePick(forcePick);
                            taskCandidateSettings.setIsPick("0");
                            taskCandidateSettings.setCreateTime(new Date());
                            taskCandidateSettings.setNextNodeHandler(nextNodeHandler);
                            taskCandidateSettings.setControlNode(controlNodeStr);
                            doTaskDeployCandidateSettingsInfo(taskCandidateSettings);
                        }
                    }
                }
            }
            if (!"VAR".equalsIgnoreCase(temp.get("type").textValue())){
                ModelTaskCandidateSettings taskCandidateSettings = new ModelTaskCandidateSettings();
                taskCandidateSettings.setDeployId(deployId);
                taskCandidateSettings.setNodeCode(nodeCode.textValue());
                taskCandidateSettings.setDataType(ConstanceVariable.PRACTICAL);
                taskCandidateSettings.setCandidateType(temp.get("type").textValue());
                taskCandidateSettings.setCandidateName(temp.get("name").textValue());
                taskCandidateSettings.setCandidateValue(temp.get("code").asText());
                taskCandidateSettings.setForcePick(forcePick);
                taskCandidateSettings.setIsPick("0");
                taskCandidateSettings.setCreateTime(new Date());
                taskCandidateSettings.setNextNodeHandler(nextNodeHandler);
                taskCandidateSettings.setControlNode(controlNodeStr);
                doTaskDeployCandidateSettingsInfo(taskCandidateSettings);
            }
        }

        if (Objects.equals("1",nextNodeHandler)){
            if (Objects.nonNull(controlNode)){
                FlowNodeCandidateControllerDomain domain = new FlowNodeCandidateControllerDomain();
                domain.setDeployId(deployId);
                domain.setNodeCode(nodeCode.textValue());
                if (controlNode instanceof ArrayNode){
                    StringBuffer sbf = new StringBuffer();
                    for (JsonNode jsonNode : controlNode) {
                        sbf.append(jsonNode.textValue()).append(",");
                    }
                    domain.setControlNodes(sbf.substring(0,sbf.length()-1));
                }
                flowNodeCandidateControllerRepository.saveFlowNodeCandidateController(domain);
            }
        }
    }

    private boolean isInvalidConfig(JsonNode copierConfigNode) {
        if (Objects.isNull(copierConfigNode) || copierConfigNode.isNull()) {
            return true;
        }
        if (!(copierConfigNode instanceof ArrayNode)) {
            return true;
        }

        return false;
    }

    private void doTaskDeployCandidateSettingsInfo(ModelTaskCandidateSettings flowTaskCandidateSettings) {
        flowTaskCandidateSettingsRepository.addTaskDeployCandidateSettingsInfo(flowTaskCandidateSettings);
    }

    /**
     * 是否处理
     *
     * @param elementNode 任务节点flowElement
     * @return 是否处理
     */
    @Override
    public boolean support(JsonNode elementNode) {
        JsonNode properties = elementNode.get("properties");
        if (nonNull(properties)) {
            return nonNull(properties.get(ConstanceVariable.OVERRIDE_ID));
        }
        return false;
    }

    /**
     * 处理
     *
     * @param context 处理上下文
     */
    @Override
    public void process(FlowElementProcessContext context) {
        saveTaskDeployCandidateSettingsInfo(context.getDeployId(), context.getElementNode(), context.getModelNode());
    }
}